/*
 * With gdbus
 */
#include <stdio.h>
#include <stdlib.h>
#include <gio/gio.h>
#include "common.h"

#define OFONO_MESSAGE_MANAGER "org.ofono.MessageManager"

#define USE_DELIVERY_REPORT "UseDeliveryReports"
#define SERVICE_CENTER_ADDRESS "ServiceCenterAddress"
#define BEARER "Bearer"
#define ALPHABET "Alphabet"

static GMainLoop *main_loop;
GDBusConnection *connection;
const gchar *modems[MODEM_COUNT_LIMIT];

static void on_response_callback(GObject *source_object, GAsyncResult *result, gpointer user_data) {
    GError *error = NULL;
    GVariant *dbus_result = NULL;
    GDBusConnection *conn = G_DBUS_CONNECTION(source_object);
    dbus_result = g_dbus_connection_call_finish(conn, result, &error);
    if (dbus_result == NULL) {
        printf("error on_response_callback: %s", error->message);
        g_error_free(error);
    }

    if (user_data != NULL) {
        g_main_loop_quit(main_loop);
    }
}

static void set_property(GVariant *parameters) {
    GError *error = NULL;
    GVariant *result = g_dbus_connection_call_sync(connection, OFONO_SERVICE_NAME, modems[0], OFONO_MESSAGE_MANAGER, 
            "SetProperty", parameters, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
    if (result == NULL) {
        printf("error: %s\n", error->message);
    }
}

static void set_property_async(GVariant *parameters, gpointer user_data) {
    g_dbus_connection_call(connection, OFONO_SERVICE_NAME, modems[0], OFONO_MESSAGE_MANAGER,
            "SetProperty", parameters, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
            (GAsyncReadyCallback) on_response_callback, user_data);
}

static void list_properties() {
    GError *error = NULL;
    GVariant *properties = g_dbus_connection_call_sync(connection, OFONO_SERVICE_NAME, modems[0], OFONO_MESSAGE_MANAGER,
            "GetProperties", NULL, ((const GVariantType *) "(a{sv})"), 
            G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
    if (properties == NULL) {
        g_print("error on GetProperties: %s\n", error->message);
        return;
    }
    /* attention: return type is '(a{sv})', so need to retrieve child whose type is a{sv} */
    iterate_dictionary(g_variant_get_child_value(properties, 0));
}

int main(int argc, char **argv) {
    gpointer callback_data;
    g_type_init();
    connection = get_system_bus_connection();
    gsize modem_count = 0;
    get_modem_paths(modems, &modem_count);
    if (modem_count < 1) {
        g_print("no modems ready, return\n");
        return -1;
    }

    g_print("before do anyting:\n");
    list_properties();
    set_property(g_variant_new("(sv)", USE_DELIVERY_REPORT, g_variant_new("b", 0)));
    set_property(g_variant_new("(sv)", SERVICE_CENTER_ADDRESS, g_variant_new("s", "123456789")));
    set_property(g_variant_new("(sv)", BEARER, g_variant_new("s", "ps-only")));
    set_property(g_variant_new("(sv)", ALPHABET, g_variant_new("s", "portuguese")));
    g_print("after synchronous call\n");
    list_properties();
    
    /* use asynchronous call, which you must finish the call in specified callback */
    g_print("now let's try asynchronous call\n");
    main_loop = g_main_loop_new(NULL, FALSE);

    g_print("now try asynchronous call\n");
    set_property_async(g_variant_new("(sv)", USE_DELIVERY_REPORT, g_variant_new("b", 1)), NULL);
    set_property_async(g_variant_new("(sv)", SERVICE_CENTER_ADDRESS, g_variant_new("s", "+86123456789")), NULL);
    set_property_async(g_variant_new("(sv)", BEARER, g_variant_new("s", "ps-preferred")), NULL);
    set_property_async(g_variant_new("(sv)", ALPHABET, g_variant_new("s", "turkish")), &modem_count);

    g_main_loop_run(main_loop);
    list_properties();
    for (int i = 0; i < modem_count; i++) {
        g_free(modems[i]);
    }
    return 0;
}
